package com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonCodeEnum;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonResult;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ExceptionCast;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ResponseResult;
import com.xyht.sca_s.student_manage_system.common.util.ApiModelUtil;
import com.xyht.sca_s.student_manage_system.common.util.CacheUtil;
import com.xyht.sca_s.student_manage_system.common.util.TimeUtil;
import com.xyht.sca_s.student_manage_system.modules.appDynamic.entity.resp.UserInfoResp;
import com.xyht.sca_s.student_manage_system.modules.newTips.entity.SmsNewTips;
import com.xyht.sca_s.student_manage_system.modules.newTips.entity.SmsNewTipsRecord;
import com.xyht.sca_s.student_manage_system.modules.newTips.mapper.SmsNewTipsMapper;
import com.xyht.sca_s.student_manage_system.modules.newTips.mapper.SmsNewTipsRecordMapper;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.AppTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.RangeTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.TipsTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.util.NewTipsUtil;
import com.xyht.sca_s.student_manage_system.modules.user.entity.SmsRole;
import com.xyht.sca_s.student_manage_system.modules.user.entity.SmsUser;
import com.xyht.sca_s.student_manage_system.modules.user.mapper.SmsRoleMapper;
import com.xyht.sca_s.student_manage_system.modules.user.mapper.SmsUserMapper;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.entity.SmsWnsStudentLoanApply;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.entity.SmsWnsStudentLoanDetail;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.entity.SmsWnsStudentLoanProcess;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.entity.req.SmsWnsStudentLoanApplyExportReq;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.entity.req.SmsWnsStudentLoanApplyReq;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.entity.req.SmsWnsStudentLoanDetailReq;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.entity.resp.SmsWnsStudentLoanApplyResp;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.entity.resp.SmsWnsStudentLoanDetailResp;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.mapper.SmsWnsStudentLoanApplyMapper;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.mapper.SmsWnsStudentLoanDetailMapper;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.mapper.SmsWnsStudentLoanProcessMapper;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.service.SmsWnsStudentLoanApplyService;
import com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.util.CategoryItemUtil;
import com.xyht.sca_s.student_manage_system.modules.workApplicationGroup.entity.SmsWorkGroupApplication;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

import static com.xyht.sca_s.student_manage_system.common.util.ParamCheckUtil.isNullOrEmpty;
import static com.xyht.sca_s.student_manage_system.modules.examinePaymentEquipment.constant.paymentExamineStatusConstant.*;
import static com.xyht.sca_s.student_manage_system.modules.student.constant.StudentInfoCommonConstant.PER_SHEET_NUM;
import static com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.constant.StudentLoanApplyConstant.*;
import static com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.constant.StudentLoanObjectTypeConstant.WNS_STUDENT_LOAN_OBJECT_TYPE_PERSON;
import static com.xyht.sca_s.student_manage_system.modules.welcomeNewStudent.constant.StudentLoanObjectTypeConstant.WNS_STUDENT_LOAN_OBJECT_TYPE_ROLE;

/**
 * <p>
 * 助学贷款申请表 服务实现类
 * </p>
 *
 * @author XYHT
 * @since 2024-03-20
 */
@Service
public class SmsWnsStudentLoanApplyServiceImpl extends ServiceImpl<SmsWnsStudentLoanApplyMapper, SmsWnsStudentLoanApply> implements SmsWnsStudentLoanApplyService {

    @Resource
    private SmsWnsStudentLoanProcessMapper smsWnsStudentLoanProcessMapper;
    @Resource
    private SmsWnsStudentLoanDetailMapper smsWnsStudentLoanDetailMapper;
    @Resource
    private NewTipsUtil newTipsUtil;
    @Resource
    private CacheUtil cacheUtil;
    @Resource
    private SmsUserMapper smsUserMapper;
    @Resource
    private SmsRoleMapper smsRoleMapper;
    @Resource
    private SmsNewTipsMapper smsNewTipsMapper;
    @Resource
    private SmsNewTipsRecordMapper smsNewTipsRecordMapper;
    @Resource
    private ApiModelUtil apiModelUtil;
    @Resource
    private CategoryItemUtil categoryItemUtil;

    @Override
    @Transactional
    public ResponseResult addStudentLoanApply(SmsWnsStudentLoanApplyReq req, String userId) {
        if (isNullOrEmpty(req.getStuName(), req.getStuIdCard(), req.getLoanBank(), req.getLoanAmount(), req.getAnnex())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        // 贷款金额不可小于0
        if (req.getLoanAmount().compareTo(BigDecimal.valueOf(0)) < 0) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        List<SmsWnsStudentLoanProcess> editProcessList = smsWnsStudentLoanProcessMapper.selectList(new LambdaQueryWrapper<SmsWnsStudentLoanProcess>()
                .eq(SmsWnsStudentLoanProcess::getProcessIsApplicationEdit, true)
                .eq(SmsWnsStudentLoanProcess::getProcessIsUse, true)
                .orderByAsc(SmsWnsStudentLoanProcess::getProcessSort));
        if (!editProcessList.isEmpty()) {
            if (req.getDetailReqList().isEmpty()) {
                return CommonResult.failed(CommonCodeEnum.WNS_STUDENT_LOAN_ALLOW_USER_NOT_SETTING);
            }
            // 校验申请人是否将全部需要编辑流程填写
            for (SmsWnsStudentLoanProcess process : editProcessList) {
                List<SmsWnsStudentLoanDetailReq> filterDetailReqList = req.getDetailReqList().stream().filter(detailReq -> detailReq.getProcessId().equals(process.getId())).collect(Collectors.toList());
                if (filterDetailReqList.isEmpty()) {
                    return CommonResult.failed(CommonCodeEnum.WNS_STUDENT_LOAN_ALLOW_PROCESS_NOT_FILL);
                }
            }
        }

        // 创建申请表
        SmsWnsStudentLoanApply apply = new SmsWnsStudentLoanApply();
        BeanUtils.copyProperties(req, apply);
        apply.setUserId(userId);
        apply.setAllowStatus(WNS_STUDENT_LOAN_STATUS_WAIT_ALLOW);
        // 设置申请人姓名
        SmsUser user = smsUserMapper.selectById(userId);
        apply.setApplyUserName(user.getRealName());
        this.save(apply);

        // 创建审批流程
        List<SmsWnsStudentLoanProcess> processList = smsWnsStudentLoanProcessMapper.selectList(new LambdaQueryWrapper<SmsWnsStudentLoanProcess>()
                .eq(SmsWnsStudentLoanProcess::getProcessIsUse, true)
                .orderByAsc(SmsWnsStudentLoanProcess::getProcessSort));
        if (processList.isEmpty()) {
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.WNS_STUDENT_LOAN_PROCESS_NOT_SETTING));
        }

        int sort = 1;
        for (SmsWnsStudentLoanProcess process : processList) {
            SmsWnsStudentLoanDetail detail = new SmsWnsStudentLoanDetail();
            detail.setApplyId(apply.getId());
            detail.setProcessId(process.getId());
            detail.setIsSign(process.getProcessIsSign());
            detail.setIsStamp(process.getProcessIsStamp());
            detail.setProcessName(process.getProcessName());
            detail.setAllowStatus(WNS_STUDENT_LOAN_STATUS_WAIT_ALLOW);
            detail.setDetailSort(sort++);

            // 申请人可编辑需保存审批人信息
            if (process.getProcessIsApplicationEdit()) {
                List<SmsWnsStudentLoanDetailReq> filterDetailReqList = req.getDetailReqList().stream().filter(detailReq -> detailReq.getProcessId().equals(process.getId())).collect(Collectors.toList());
                SmsWnsStudentLoanDetailReq detailReq = filterDetailReqList.get(0);
                if (isNullOrEmpty(detailReq.getProcessObjectId())) {
                    ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
                }

                detail.setProcessObjectType(WNS_STUDENT_LOAN_OBJECT_TYPE_PERSON);
                detail.setProcessObjectId(detailReq.getProcessObjectId());
            } else {
                detail.setProcessObjectId(process.getProcessObjectId());
                detail.setProcessObjectType(process.getProcessObjectType());
            }

            smsWnsStudentLoanDetailMapper.insert(detail);
        }

        // 消息通知
        // 通知流程第一个节点
        SmsWnsStudentLoanDetail firstDetail = smsWnsStudentLoanDetailMapper.selectOne(new LambdaQueryWrapper<SmsWnsStudentLoanDetail>()
                .eq(SmsWnsStudentLoanDetail::getApplyId, apply.getId())
                .eq(SmsWnsStudentLoanDetail::getDetailSort, 1)
                .orderByAsc(SmsWnsStudentLoanDetail::getDetailSort));
        RangeTypeEnum rangeTypeEnum;
        if (firstDetail.getProcessObjectType() == WNS_STUDENT_LOAN_OBJECT_TYPE_PERSON) {
            rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
        } else {
            rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_ROLE;
        }
        List<String> rangeList = new ArrayList<>();
        rangeList.add(firstDetail.getProcessObjectId());

        newTipsUtil.addNewTips(TipsTypeEnum.TIPS_TYPE_ENUM_ALLOW,
                userId,
                rangeTypeEnum,
                rangeList,
                AppTypeEnum.APP_TYPE_ENUM_STUDENT_LOAN,
                apply.getId(),
                firstDetail.getId());
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult cancelStudentLoanApply(SmsWnsStudentLoanApplyReq req, String userId) {
        if (isNullOrEmpty(req.getId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        SmsWnsStudentLoanApply apply = this.getById(req.getId());
        if (apply == null || !apply.getUserId().equals(userId)) {
            return CommonResult.failed(CommonCodeEnum.WNS_STUDENT_LOAN_NOT_EXIST);
        }
        // 已经开始审批不可撤回
        if (apply.getAllowStatus() != WNS_STUDENT_LOAN_STATUS_WAIT_ALLOW) {
            return CommonResult.failed(CommonCodeEnum.WNS_STUDENT_LOAN_CANCEL_FAIL_ALLOWED);
        }

        // 撤回审批
        apply.setAllowStatus(WNS_STUDENT_LOAN_STATUS_CANCEL);
        apply.setEndTime(new Date());
        this.updateById(apply);

        // 修改节点状态
        SmsWnsStudentLoanDetail detail = new SmsWnsStudentLoanDetail();
        detail.setAllowStatus(WNS_STUDENT_LOAN_STATUS_CANCEL);
        smsWnsStudentLoanDetailMapper.update(detail, new LambdaQueryWrapper<SmsWnsStudentLoanDetail>()
                .eq(SmsWnsStudentLoanDetail::getApplyId, req.getId())
                .eq(SmsWnsStudentLoanDetail::getAllowStatus, WNS_STUDENT_LOAN_STATUS_WAIT_ALLOW));

        // 消息通知
        newTipsUtil.cancelFinishTips(req.getId());
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult allowStudentLoanApply(SmsWnsStudentLoanDetailReq req, String userId) {
        if (isNullOrEmpty(req.getId(), req.getAllowStatus())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        if (req.getAllowStatus() != WNS_STUDENT_LOAN_STATUS_PASS && req.getAllowStatus() != WNS_STUDENT_LOAN_STATUS_DENY) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        SmsWnsStudentLoanDetail detail = smsWnsStudentLoanDetailMapper.selectById(req.getId());
        if (detail == null || detail.getAllowStatus() != WNS_STUDENT_LOAN_STATUS_WAIT_ALLOW) {
            return CommonResult.failed(CommonCodeEnum.WNS_STUDENT_LOAN_ALLOW_FAIL);
        }

        // 判断该节点是否本人审批（防止跳节点审批）
        if (detail.getProcessObjectType() == WNS_STUDENT_LOAN_OBJECT_TYPE_PERSON) {
            if (!detail.getProcessObjectId().equals(userId)) {
                return CommonResult.failed(CommonCodeEnum.WNS_STUDENT_LOAN_ALLOW_FAIL);
            }
        } else {
            List<String> roleList = cacheUtil.getRoleList(userId);
            List<String> filterRoleList = roleList.stream().filter(role -> role.equals(detail.getProcessObjectId())).collect(Collectors.toList());
            if (filterRoleList.isEmpty()) {
                return CommonResult.failed(CommonCodeEnum.WNS_STUDENT_LOAN_ALLOW_FAIL);
            }
        }

        // 校验前一个结点是否审批
        if (!detail.getDetailSort().equals(1)) {
            SmsWnsStudentLoanDetail preDetail = smsWnsStudentLoanDetailMapper.selectOne(new LambdaQueryWrapper<SmsWnsStudentLoanDetail>()
                    .eq(SmsWnsStudentLoanDetail::getApplyId, detail.getApplyId())
                    .eq(SmsWnsStudentLoanDetail::getDetailSort, detail.getDetailSort() - 1));
            if (preDetail != null) {
                if (preDetail.getAllowStatus() != WNS_STUDENT_LOAN_STATUS_PASS) {
                    return CommonResult.failed(CommonCodeEnum.WNS_STUDENT_LOAN_ALLOW_FAIL);
                }
            }
        }

        // 更新节点
        detail.setAllowStatus(req.getAllowStatus());
        if (!isNullOrEmpty(req.getDetailAllowOption())) {
            detail.setDetailAllowOption(req.getDetailAllowOption());
        }
        Date nowDate = new Date();
        detail.setDetailAllowTime(nowDate);
        detail.setAllowUserId(userId);

        if (detail.getIsSign()) {
            if (isNullOrEmpty(req.getSign())) {
                ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
            }
            detail.setSign(req.getSign());
        }
        if (detail.getIsStamp()) {
            if (isNullOrEmpty(req.getStamp())) {
                ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
            }
            detail.setStamp(req.getStamp());
        }
        smsWnsStudentLoanDetailMapper.updateById(detail);

        // 流程是否结束标志
        boolean is_done = false;
        // 判断是否最后一个节点 是否驳回
        SmsWnsStudentLoanDetail nextDetail = smsWnsStudentLoanDetailMapper.selectOne(new LambdaQueryWrapper<SmsWnsStudentLoanDetail>()
                .eq(SmsWnsStudentLoanDetail::getApplyId, detail.getApplyId())
                .eq(SmsWnsStudentLoanDetail::getDetailSort, detail.getDetailSort() + 1));
        if (nextDetail == null || req.getAllowStatus() == WNS_STUDENT_LOAN_STATUS_DENY) {
            is_done = true;

            SmsWnsStudentLoanApply apply = new SmsWnsStudentLoanApply();
            apply.setId(detail.getApplyId());
            apply.setEndTime(nowDate);
            apply.setAllowStatus(req.getAllowStatus());
            this.updateById(apply);
        }

        // 节点驳回 重置其余节点状态
        if (req.getAllowStatus() == WNS_STUDENT_LOAN_STATUS_DENY) {
            SmsWnsStudentLoanDetail updateDetail = new SmsWnsStudentLoanDetail();
            updateDetail.setAllowStatus(WNS_STUDENT_LOAN_STATUS_DENY_FINISH);
            smsWnsStudentLoanDetailMapper.update(updateDetail, new LambdaQueryWrapper<SmsWnsStudentLoanDetail>()
                    .eq(SmsWnsStudentLoanDetail::getApplyId, detail.getApplyId())
                    .eq(SmsWnsStudentLoanDetail::getAllowStatus, WNS_STUDENT_LOAN_STATUS_WAIT_ALLOW));
        }

        // 消息通知
        if (is_done) {
            boolean result_status = false;
            if (req.getAllowStatus() == WNS_STUDENT_LOAN_STATUS_PASS) {
                result_status = true;

                // 申请成功获得助学贷款可分配金额
                // 添加失败抛出异常
                if (!categoryItemUtil.addStudentLoanAmount(detail.getApplyId())) {
                    ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.FAIL));
                }
            }
            newTipsUtil.allowFinishTips(detail.getApplyId(), userId, result_status);
        } else {
            RangeTypeEnum rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
            if (nextDetail.getProcessObjectType() == WNS_STUDENT_LOAN_OBJECT_TYPE_ROLE) {
                rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_ROLE;
            }
            List<String> rangeIDList = new ArrayList<>();
            rangeIDList.add(nextDetail.getProcessObjectId());
            newTipsUtil.allowContinueTips(detail.getApplyId(),
                    userId,
                    rangeTypeEnum,
                    rangeIDList,
                    nextDetail.getId());
        }
        return CommonResult.success();
    }

    @Override
    public ResponseResult getStudentLoanApplyList(Integer pageNum, Integer pageSize, Integer applyType, String searchStr, String userId) {
        if (!WNS_STUDENT_LOAN_TYPE_LIST.contains(applyType)) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        LambdaQueryWrapper<SmsWnsStudentLoanApply> queryWrapper = new LambdaQueryWrapper<SmsWnsStudentLoanApply>()
                .orderByDesc(SmsWnsStudentLoanApply::getCreateTime);
        if (!isNullOrEmpty(searchStr)) {
            queryWrapper.and(i -> i.like(SmsWnsStudentLoanApply::getStuName, searchStr).or()
                    .like(SmsWnsStudentLoanApply::getStuIdCard, searchStr).or()
                    .like(SmsWnsStudentLoanApply::getLoanBank, searchStr).or()
                    .like(SmsWnsStudentLoanApply::getLoanAmount, searchStr).or()
                    .like(SmsWnsStudentLoanApply::getApplyUserName, searchStr));
        }

        if (applyType == WNS_STUDENT_LOAN_TYPE_ALLOW_WAIT_ME) {
            // 获取本人角色
            List<String> roleList = cacheUtil.getRoleList(userId);

            List<SmsWnsStudentLoanDetail> detailList = smsWnsStudentLoanDetailMapper.selectList(new LambdaQueryWrapper<SmsWnsStudentLoanDetail>()
                    .eq(SmsWnsStudentLoanDetail::getAllowStatus, WNS_STUDENT_LOAN_STATUS_WAIT_ALLOW)
                    .and(i -> i.eq(SmsWnsStudentLoanDetail::getProcessObjectType, WNS_STUDENT_LOAN_OBJECT_TYPE_PERSON)
                            .eq(SmsWnsStudentLoanDetail::getProcessObjectId, userId)
                            .or()
                            .eq(SmsWnsStudentLoanDetail::getProcessObjectType, WNS_STUDENT_LOAN_OBJECT_TYPE_ROLE)
                            .in(SmsWnsStudentLoanDetail::getProcessObjectId, roleList)));
            List<SmsWnsStudentLoanDetail> filterDetailList = detailList.stream().filter(detail -> {
                if (detail.getDetailSort().equals(1)) {
                    return true;
                }

                // 判断上一个流程节点是否完成
                SmsWnsStudentLoanDetail preDetail = smsWnsStudentLoanDetailMapper.selectOne(new LambdaQueryWrapper<SmsWnsStudentLoanDetail>()
                        .eq(SmsWnsStudentLoanDetail::getApplyId, detail.getApplyId())
                        .eq(SmsWnsStudentLoanDetail::getDetailSort, detail.getDetailSort() - 1)
                        .eq(SmsWnsStudentLoanDetail::getAllowStatus, WNS_STUDENT_LOAN_STATUS_PASS));
                if (preDetail != null) {
                    return true;
                }
                return false;
            }).collect(Collectors.toList());

            // 构造筛选条件
            if (filterDetailList.isEmpty()) {
                queryWrapper.in(SmsWnsStudentLoanApply::getId, "");
            } else {
                List<String> applyIdList = filterDetailList.stream().map(SmsWnsStudentLoanDetail::getApplyId).distinct().collect(Collectors.toList());
                queryWrapper.in(SmsWnsStudentLoanApply::getId, applyIdList);
            }
        } else if (applyType == WNS_STUDENT_LOAN_TYPE_ALLOWED) {
            List<SmsWnsStudentLoanDetail> detailList = smsWnsStudentLoanDetailMapper.selectList(new LambdaQueryWrapper<SmsWnsStudentLoanDetail>()
                    .eq(SmsWnsStudentLoanDetail::getAllowUserId, userId)
                    .and(i -> i.eq(SmsWnsStudentLoanDetail::getAllowStatus, WNS_STUDENT_LOAN_STATUS_PASS)
                            .or()
                            .eq(SmsWnsStudentLoanDetail::getAllowStatus, WNS_STUDENT_LOAN_STATUS_DENY)));

            // 构造筛选条件
            if (detailList.isEmpty()) {
                queryWrapper.in(SmsWnsStudentLoanApply::getId, "");
            } else {
                List<String> applyIdList = detailList.stream().map(SmsWnsStudentLoanDetail::getApplyId).distinct().collect(Collectors.toList());
                queryWrapper.in(SmsWnsStudentLoanApply::getId, applyIdList);
            }
        } else if (applyType == WNS_STUDENT_LOAN_TYPE_APPLY) {
            queryWrapper.eq(SmsWnsStudentLoanApply::getUserId, userId);
        }

        Page<SmsWnsStudentLoanApply> page = new Page<>(pageNum, pageSize);
        this.page(page, queryWrapper);
        List<SmsWnsStudentLoanApplyResp> collect = page.getRecords().stream().map(apply -> {
            SmsWnsStudentLoanApplyResp applyResp = new SmsWnsStudentLoanApplyResp();
            BeanUtils.copyProperties(apply, applyResp);

            // 设置申请人信息
            SmsUser smsUser = smsUserMapper.selectById(apply.getUserId());
            UserInfoResp applyUserInfo = new UserInfoResp();
            if (smsUser != null) {
                BeanUtils.copyProperties(smsUser, applyUserInfo);
            }
            applyResp.setApplyUserInfo(applyUserInfo);

            return applyResp;
        }).collect(Collectors.toList());

        return CommonResult.success(collect, (int) page.getTotal());
    }

    @Override
    public ResponseResult getStudentLoanApplyDetail(String id, String userId) {
        SmsWnsStudentLoanApply apply = this.getById(id);
        if (apply == null) {
            return CommonResult.failed(CommonCodeEnum.WNS_STUDENT_LOAN_NOT_EXIST);
        }

        SmsWnsStudentLoanApplyResp applyResp = new SmsWnsStudentLoanApplyResp();
        BeanUtils.copyProperties(apply, applyResp);
        // 设置申请人信息
        SmsUser smsUser = cacheUtil.getUserInfo(applyResp.getUserId());
        if (smsUser != null) {
            UserInfoResp applyUserInfo = new UserInfoResp();
            BeanUtils.copyProperties(smsUser, applyUserInfo);
            applyResp.setApplyUserInfo(applyUserInfo);
        }

        List<SmsWnsStudentLoanDetailResp> detailRespList = smsWnsStudentLoanDetailMapper.selectList(new LambdaQueryWrapper<SmsWnsStudentLoanDetail>()
                        .eq(SmsWnsStudentLoanDetail::getApplyId, apply.getId())
                        .orderByAsc(SmsWnsStudentLoanDetail::getDetailSort))
                .stream().map(detail -> {
                    SmsWnsStudentLoanDetailResp detailResp = new SmsWnsStudentLoanDetailResp();
                    BeanUtils.copyProperties(detail, detailResp);

                    // 设置审批人信息
                    if (detailResp.getProcessObjectType() == WNS_STUDENT_LOAN_OBJECT_TYPE_PERSON) {
                        SmsUser allowUser = smsUserMapper.selectById(detailResp.getProcessObjectId());
                        if (allowUser != null) {
                            detailResp.setRealName(allowUser.getRealName());
                            detailResp.setHeadPic(allowUser.getUserPic());
                        }
                    } else if (detailResp.getProcessObjectType() == WNS_STUDENT_LOAN_OBJECT_TYPE_ROLE) {
                        SmsRole smsRole = smsRoleMapper.selectById(detailResp.getProcessObjectId());
                        if (!isNullOrEmpty(smsRole)) {
                            detailResp.setRealName(smsRole.getRoleName());
                        }
                    }

                    if (!isNullOrEmpty(detailResp.getAllowUserId())) {
                        SmsUser userInfo = cacheUtil.getUserInfo(detailResp.getAllowUserId());
                        UserInfoResp userInfoResp = new UserInfoResp();
                        if (userInfo != null) {
                            BeanUtils.copyProperties(userInfo, userInfoResp);
                        }
                        detailResp.setAllowUserInfo(userInfoResp);
                    }

                    return detailResp;
                }).collect(Collectors.toList());
        applyResp.setDetailRespList(detailRespList);

        return CommonResult.success(applyResp);
    }

    @Override
    public ResponseResult getStudentLoanApplyOriginSettingProcess() {
        List<SmsWnsStudentLoanProcess> processList = smsWnsStudentLoanProcessMapper.selectList(new LambdaQueryWrapper<SmsWnsStudentLoanProcess>()
                .eq(SmsWnsStudentLoanProcess::getProcessIsApplicationEdit, true)
                .eq(SmsWnsStudentLoanProcess::getProcessIsUse, true)
                .orderByAsc(SmsWnsStudentLoanProcess::getProcessSort));
        return CommonResult.success(processList);
    }

    @Override
    public ResponseResult selectAllStudentLoanApply(Integer pageNum, Integer pageSize, Integer allowStatus, String searchStr) {
        LambdaQueryWrapper<SmsWnsStudentLoanApply> queryWrapper = new LambdaQueryWrapper<SmsWnsStudentLoanApply>()
                .orderByDesc(SmsWnsStudentLoanApply::getCreateTime);
        // 审批状态
        if (allowStatus != null) {
            queryWrapper.eq(SmsWnsStudentLoanApply::getAllowStatus, allowStatus);
        }

        if (!isNullOrEmpty(searchStr)) {
            queryWrapper.and(i -> i.like(SmsWnsStudentLoanApply::getStuName, searchStr).or()
                    .like(SmsWnsStudentLoanApply::getStuIdCard, searchStr).or()
                    .like(SmsWnsStudentLoanApply::getLoanBank, searchStr).or()
                    .like(SmsWnsStudentLoanApply::getLoanAmount, searchStr).or()
                    .like(SmsWnsStudentLoanApply::getApplyUserName, searchStr));
        }

        Page<SmsWnsStudentLoanApply> page = new Page<>(pageNum, pageSize);
        this.page(page, queryWrapper);
        List<SmsWnsStudentLoanApplyResp> collect = page.getRecords().stream().map(apply -> {
            SmsWnsStudentLoanApplyResp applyResp = new SmsWnsStudentLoanApplyResp();
            BeanUtils.copyProperties(apply, applyResp);

            // 设置申请人
            SmsUser smsUser = cacheUtil.getUserInfo(apply.getUserId());
            if (smsUser != null) {
                UserInfoResp userInfoResp = new UserInfoResp();
                BeanUtils.copyProperties(smsUser, userInfoResp);
                applyResp.setApplyUserInfo(userInfoResp);
            }

            return applyResp;
        }).collect(Collectors.toList());

        return CommonResult.success(collect, (int) page.getTotal());
    }

    @Override
    @Async
    public Future<ResponseResult> exportStudentLoanApply(SmsWnsStudentLoanApplyExportReq req, HttpServletResponse response) {
        if (isNullOrEmpty(req.getIsExportProcess(), req.getLimitColumn())) {
            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
        }

        // 构造查询条件
        LambdaQueryWrapper<SmsWnsStudentLoanApply> queryWrapper = new LambdaQueryWrapper<SmsWnsStudentLoanApply>()
                .orderByDesc(SmsWnsStudentLoanApply::getCreateTime);
        if (!isNullOrEmpty(req.getStuName())) {
            queryWrapper.like(SmsWnsStudentLoanApply::getStuName, req.getStuName());
        }
        if (!isNullOrEmpty(req.getStuIdCard())) {
            queryWrapper.eq(SmsWnsStudentLoanApply::getStuIdCard, req.getStuIdCard());
        }
        if (!isNullOrEmpty(req.getLoanBank())) {
            queryWrapper.eq(SmsWnsStudentLoanApply::getLoanBank, req.getLoanBank());
        }
        if (!isNullOrEmpty(req.getAllowStatus())) {
            queryWrapper.eq(SmsWnsStudentLoanApply::getAllowStatus, req.getAllowStatus());
        }

        // 获取要导出的申请表
        List<SmsWnsStudentLoanApply> applyList = this.list(queryWrapper);

        try {
            // 表头数据
            String[] header = req.getLimitColumn().toArray(new String[0]);
            double sheetNum;
            // 声明一个工作簿
            HSSFWorkbook workbook = new HSSFWorkbook();
            if (applyList != null && applyList.size() > 0) {
                sheetNum = Math.ceil((double) applyList.size() / PER_SHEET_NUM);
                for (int k = 0; k < sheetNum; k++) {
                    // 生成一个表格，设置表格名称
                    HSSFSheet sheet = workbook.createSheet("助学贷款申请记录导出表" + (k + 1));

                    // 设置表格列宽度为10个字节
                    sheet.setDefaultColumnWidth(12);
                    // 创建标题的显示样式
                    HSSFCellStyle headerStyle = workbook.createCellStyle();
                    headerStyle.setFillForegroundColor(IndexedColors.YELLOW.index);
                    headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

                    HSSFFont f = workbook.createFont();
                    f.setFontHeightInPoints((short) 10); // 字号
                    f.setBold(true); // 加粗
                    headerStyle.setFont(f);
                    // 创建第一行表头
                    HSSFRow headRow = sheet.createRow(0);

                    // 遍历添加表头(下面模拟遍历学生，也是同样的操作过程)
                    for (int i = 0; i < header.length + 1; i++) {
                        // 创建一个单元格
                        HSSFCell cell = headRow.createCell(i);

                        if (i == 0) {
                            // 创建一个内容对象
                            HSSFRichTextString text = new HSSFRichTextString("序号");
                            // 将内容对象的文字内容写入到单元格中
                            cell.setCellValue(text);
                            cell.setCellStyle(headerStyle);
                            continue;
                        }

                        // 创建一个内容对象
                        String header1 = apiModelUtil.getFieldValueByFieldName(SmsWorkGroupApplication.class, header[i - 1]);
                        HSSFRichTextString text = new HSSFRichTextString(header1);

                        // 将内容对象的文字内容写入到单元格中
                        cell.setCellValue(text);
                        cell.setCellStyle(headerStyle);
                    }

                    // 判断是否需要添加流程表头
                    if (req.getIsExportProcess()) {
                        List<SmsWnsStudentLoanProcess> processList =
                                smsWnsStudentLoanProcessMapper.selectList(new QueryWrapper<>());
                        if (processList != null && processList.size() > 0) {
                            int origin_num = header.length + 1;
                            for (SmsWnsStudentLoanProcess process : processList) {
                                String process_name = process.getProcessName();
                                addProcessTableHead(headRow, headerStyle, origin_num, process_name);
                                origin_num += 4;
                            }
                        }
                    }

                    int range = PER_SHEET_NUM;
                    if (k + 1 == sheetNum) {
                        range = applyList.size() - (PER_SHEET_NUM) * k;
                    }
                    for (int i = 0; i < range; i++) {
                        // 创建一行
                        HSSFRow row1 = sheet.createRow(i + 1);
                        SmsWnsStudentLoanApply apply = applyList.get((PER_SHEET_NUM) * k + i);
                        Map map = JSONObject.parseObject(JSON.toJSONString(apply), Map.class);
                        row1.createCell(0).setCellValue(new HSSFRichTextString(String.valueOf(i + 1)));
                        for (int j = 0; j < header.length; j++) {
                            String rowContent = "";
                            if (map.get(header[j]) instanceof Long) {
                                rowContent = TimeUtil.DateformatTimestamp((long) map.get(header[j]));
                            } else {
                                rowContent = String.valueOf(map.get(header[j]));
                            }
                            row1.createCell(j + 1).setCellValue(new HSSFRichTextString(rowContent));
                        }

                        if (req.getIsExportProcess()) {
                            List<SmsWnsStudentLoanProcess> processList = smsWnsStudentLoanProcessMapper.selectList(new QueryWrapper<>());
                            if (processList != null && processList.size() > 0) {
                                int origin_num = header.length + 1;
                                for (SmsWnsStudentLoanProcess process : processList) {
                                    SmsWnsStudentLoanDetail detail = smsWnsStudentLoanDetailMapper.selectOne(new LambdaQueryWrapper<SmsWnsStudentLoanDetail>()
                                            .eq(SmsWnsStudentLoanDetail::getApplyId, apply.getId())
                                            .eq(SmsWnsStudentLoanDetail::getProcessId, process.getId()));
                                    if (detail == null) {
                                        origin_num += 4;
                                    } else {
                                        // 审批人
                                        SmsUser user = cacheUtil.getUserInfo(detail.getAllowUserId());
                                        if (user == null) {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(""));
                                        } else {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(user.getRealName()));
                                        }

                                        // 审批时间
                                        Date allow_time = detail.getDetailAllowTime();
                                        if (allow_time == null) {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(""));
                                        } else {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(TimeUtil.DateHanZiSimpleFormat(allow_time)));
                                        }

                                        // 审批状态
                                        Integer allow_status = detail.getAllowStatus();
                                        if (allow_status == EXAMINE_STATUS_PASS || allow_status == EXAMINE_STATUS_FORCED_FINISH) {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString("同意"));
                                        } else if (allow_status == EXAMINE_STATUS_DENY || allow_status == EXAMINE_STATUS_FORCED_REJECT) {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString("拒绝"));
                                        } else {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(""));
                                        }

                                        // 审批意见
                                        String allow_option = detail.getDetailAllowOption();
                                        if (isNullOrEmpty(allow_option)) {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(""));
                                        } else {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(allow_option));
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

//            response.reset();
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("助学贷款申请记录导出表.xlsx", "utf-8"));
            response.setCharacterEncoding("utf-8");
            response.setHeader("file-type", "download");
            response.setHeader("file-name", URLEncoder.encode("助学贷款申请记录导出表.xlsx", "utf-8"));
            response.setHeader("Access-Control-Expose-Headers", "file-type,file-name");
//          // 刷新缓冲
            response.flushBuffer();
            // workbook将Excel写入到response的输出流中，供页面下载
            OutputStream os = response.getOutputStream();
            workbook.write(os);

            workbook.close();
            os.close();
        } catch (Exception e) {
            e.printStackTrace();
            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.FAIL));
        }
        return null;
    }

    private void addProcessTableHead(HSSFRow headRow, HSSFCellStyle headerStyle, Integer origin_cell_num, String originHeadContent) {
        Integer cell_num = origin_cell_num;

        setTableHead(headRow, headerStyle, cell_num++, originHeadContent + "审批人");
        setTableHead(headRow, headerStyle, cell_num++, originHeadContent + "审批时间");
        setTableHead(headRow, headerStyle, cell_num++, originHeadContent + "审批状态");
        setTableHead(headRow, headerStyle, cell_num, originHeadContent + "审批意见");

    }

    private void setTableHead(HSSFRow headRow, HSSFCellStyle headerStyle, Integer cell_num, String headContent) {
        HSSFCell cell = headRow.createCell(cell_num);
        // 创建一个内容对象
        HSSFRichTextString text = new HSSFRichTextString(headContent);

        // 将内容对象的文字内容写入到单元格中
        cell.setCellValue(text);
        cell.setCellStyle(headerStyle);
    }

    @Override
    @Transactional
    public ResponseResult forcedFinishStudentLoanApply(SmsWnsStudentLoanDetailReq req, String userId) {
        if (isNullOrEmpty(req.getId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        SmsWnsStudentLoanApply apply = this.getById(req.getId());
        if (apply == null) {
            return CommonResult.failed(CommonCodeEnum.WNS_STUDENT_LOAN_NOT_EXIST);
        }
        // 校验是否待审批状态
        if (apply.getAllowStatus() != WNS_STUDENT_LOAN_STATUS_WAIT_ALLOW) {
            return CommonResult.failed(CommonCodeEnum.WNS_STUDENT_LOAN_NOT_FORCED);
        }

        // 修改审批表状态为通过
        Date nowDate = new Date();
        apply.setAllowStatus(WNS_STUDENT_LOAN_STATUS_PASS);
        apply.setEndTime(nowDate);
        this.updateById(apply);

        // 修改节点为强制归档
        SmsWnsStudentLoanDetail detail = new SmsWnsStudentLoanDetail();
        detail.setAllowStatus(WNS_STUDENT_LOAN_STATUS_FORCED_FINISH);
        detail.setAllowUserId(userId);
        detail.setDetailAllowTime(nowDate);
        smsWnsStudentLoanDetailMapper.update(detail, new LambdaQueryWrapper<SmsWnsStudentLoanDetail>()
                .eq(SmsWnsStudentLoanDetail::getApplyId, apply.getId())
                .eq(SmsWnsStudentLoanDetail::getAllowStatus, WNS_STUDENT_LOAN_STATUS_WAIT_ALLOW));

        // 消息通知
        newTipsUtil.cancelFinishTips(apply.getId());
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult forcedTorsionStudentLoanApply(SmsWnsStudentLoanDetailReq req) {
        if (isNullOrEmpty(req.getId(), req.getProcessObjectType(), req.getProcessObjectId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        SmsWnsStudentLoanDetail detail = smsWnsStudentLoanDetailMapper.selectById(req.getId());
        if (detail == null) {
            return CommonResult.failed(CommonCodeEnum.WNS_STUDENT_LOAN_DETAIL_NOT_FORCED);
        }
        // 只有待审批才能强制流转
        if (detail.getAllowStatus() != WNS_STUDENT_LOAN_STATUS_WAIT_ALLOW) {
            return CommonResult.failed(CommonCodeEnum.WNS_STUDENT_LOAN_NOT_TORSION);
        }

        detail.setProcessObjectType(req.getProcessObjectType());
        detail.setProcessObjectId(req.getProcessObjectId());
        smsWnsStudentLoanDetailMapper.updateById(detail);

        // 消息通知
        // 判断第一节点直接发消息,其他要前节点审批后才发该节点通知
        boolean flag = true;
        if (!detail.getDetailSort().equals(1)) {
            SmsWnsStudentLoanDetail prevDetail = smsWnsStudentLoanDetailMapper.selectOne(new LambdaQueryWrapper<SmsWnsStudentLoanDetail>()
                    .eq(SmsWnsStudentLoanDetail::getApplyId, detail.getApplyId())
                    .eq(SmsWnsStudentLoanDetail::getDetailSort, detail.getDetailSort() - 1));
            if (prevDetail.getAllowStatus() != WNS_STUDENT_LOAN_STATUS_PASS) {
                flag = false;
            }
        }
        if (flag) {
            RangeTypeEnum rangeTypeEnum;
            if (detail.getProcessObjectType() == WNS_STUDENT_LOAN_OBJECT_TYPE_PERSON) {
                rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
            } else {
                rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_ROLE;
            }
            List<String> rangeList = new ArrayList<>();
            rangeList.add(detail.getProcessObjectId());
            newTipsUtil.allowContinueTips(detail.getApplyId(),
                    null,
                    rangeTypeEnum,
                    rangeList,
                    detail.getId());
        }
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult replaceApplyStudentLoanApply(String userId, SmsWnsStudentLoanDetailReq req) {
        if (isNullOrEmpty(req.getId(), req.getAllowStatus())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        if (req.getAllowStatus() != WNS_STUDENT_LOAN_STATUS_PASS && req.getAllowStatus() != WNS_STUDENT_LOAN_STATUS_DENY) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        // 校验节点是否待审批
        SmsWnsStudentLoanDetail detail = smsWnsStudentLoanDetailMapper.selectById(req.getId());
        if (detail == null || detail.getAllowStatus() != WNS_STUDENT_LOAN_STATUS_WAIT_ALLOW) {
            return CommonResult.failed(CommonCodeEnum.WNS_STUDENT_LOAN_ALLOW_FAIL);
        }

        // 校验前一个节点是否通过
        if (detail.getDetailSort() != 1) {
            SmsWnsStudentLoanDetail prevDetail = smsWnsStudentLoanDetailMapper.selectOne(new LambdaQueryWrapper<SmsWnsStudentLoanDetail>()
                    .eq(SmsWnsStudentLoanDetail::getApplyId, detail.getApplyId())
                    .eq(SmsWnsStudentLoanDetail::getDetailSort, detail.getDetailSort() - 1)
                    .eq(SmsWnsStudentLoanDetail::getAllowStatus, WNS_STUDENT_LOAN_STATUS_PASS));
            if (prevDetail == null) {
                return CommonResult.failed(CommonCodeEnum.WNS_STUDENT_LOAN_ALLOW_FAIL);
            }
        }

        // 修改节点
        detail.setAllowStatus(req.getAllowStatus());
        if (!isNullOrEmpty(req.getDetailAllowOption())) {
            detail.setDetailAllowOption(req.getDetailAllowOption());
        }
        Date nowDate = new Date();
        detail.setDetailAllowTime(nowDate);
        detail.setAllowUserId(userId);
        if (!isNullOrEmpty(req.getSign())) {
            detail.setSign(req.getSign());
        }
        if (!isNullOrEmpty(req.getStamp())) {
            detail.setStamp(req.getStamp());
        }
        smsWnsStudentLoanDetailMapper.updateById(detail);

        // 流程是否结束标志
        boolean is_done = false;
        // 判断是否最后一个节点 是否驳回
        SmsWnsStudentLoanDetail nextDetail = smsWnsStudentLoanDetailMapper.selectOne(new LambdaQueryWrapper<SmsWnsStudentLoanDetail>()
                .eq(SmsWnsStudentLoanDetail::getApplyId, detail.getApplyId())
                .eq(SmsWnsStudentLoanDetail::getDetailSort, detail.getDetailSort() + 1));
        if (nextDetail == null || req.getAllowStatus() == WNS_STUDENT_LOAN_STATUS_DENY) {
            is_done = true;

            SmsWnsStudentLoanApply apply = new SmsWnsStudentLoanApply();
            apply.setId(detail.getApplyId());
            apply.setEndTime(nowDate);
            apply.setAllowStatus(req.getAllowStatus());
            this.updateById(apply);
        }

        // 节点驳回 重置其余节点状态
        if (req.getAllowStatus() == WNS_STUDENT_LOAN_STATUS_DENY) {
            SmsWnsStudentLoanDetail updateDetail = new SmsWnsStudentLoanDetail();
            updateDetail.setAllowStatus(WNS_STUDENT_LOAN_STATUS_DENY_FINISH);
            smsWnsStudentLoanDetailMapper.update(updateDetail, new LambdaQueryWrapper<SmsWnsStudentLoanDetail>()
                    .eq(SmsWnsStudentLoanDetail::getApplyId, detail.getApplyId())
                    .eq(SmsWnsStudentLoanDetail::getAllowStatus, WNS_STUDENT_LOAN_STATUS_WAIT_ALLOW));
        }

        // 消息通知
        if (is_done) {
            boolean result_status = false;
            if (req.getAllowStatus() == WNS_STUDENT_LOAN_STATUS_PASS) {
                result_status = true;

                // 申请成功获得助学贷款可分配金额
                // 添加失败抛出异常
                if (!categoryItemUtil.addStudentLoanAmount(detail.getApplyId())) {
                    ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.FAIL));
                }
            }
            newTipsUtil.allowFinishTips(detail.getApplyId(), userId, result_status);
        } else {
            RangeTypeEnum rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
            if (nextDetail.getProcessObjectType() == WNS_STUDENT_LOAN_OBJECT_TYPE_ROLE) {
                rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_ROLE;
            }
            List<String> rangeIDList = new ArrayList<>();
            rangeIDList.add(nextDetail.getProcessObjectId());
            newTipsUtil.allowContinueTips(detail.getApplyId(),
                    userId,
                    rangeTypeEnum,
                    rangeIDList,
                    nextDetail.getId());
        }
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult forcedRejectStudentLoanApply(SmsWnsStudentLoanDetailReq req, String userId) {
        if (isNullOrEmpty(req.getApplyId(), req.getDetailAllowOption())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        SmsWnsStudentLoanApply apply = this.getById(req.getApplyId());
        if (apply == null) {
            return CommonResult.failed(CommonCodeEnum.WNS_STUDENT_LOAN_NOT_EXIST);
        }

        // 总状态只有待审批才能强制驳回
        if (apply.getAllowStatus() != WNS_STUDENT_LOAN_STATUS_WAIT_ALLOW) {
            return CommonResult.failed(CommonCodeEnum.WNS_STUDENT_LOAN_NOT_FORCED_REJECT);
        }

        // 修改申请表状态为驳回
        apply.setAllowStatus(WNS_STUDENT_LOAN_STATUS_DENY);
        Date nowDate = new Date();
        apply.setEndTime(nowDate);
        this.updateById(apply);

        // 修改节点状态 和审批人 时间
        SmsWnsStudentLoanDetail detail = new SmsWnsStudentLoanDetail();
        detail.setAllowUserId(userId);
        detail.setAllowStatus(WNS_STUDENT_LOAN_STATUS_FORCED_REJECT);
        detail.setDetailAllowTime(nowDate);
        detail.setDetailAllowOption(req.getDetailAllowOption());
        smsWnsStudentLoanDetailMapper.update(detail, new LambdaQueryWrapper<SmsWnsStudentLoanDetail>()
                .eq(SmsWnsStudentLoanDetail::getApplyId, req.getApplyId())
                .eq(SmsWnsStudentLoanDetail::getAllowStatus, WNS_STUDENT_LOAN_STATUS_WAIT_ALLOW));

        // 消息提醒
        newTipsUtil.cancelFinishTips(req.getApplyId());
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult deletedStudentLoanApply(String id) {
        SmsWnsStudentLoanApply apply = this.getById(id);
        if (apply == null) {
            return CommonResult.failed(CommonCodeEnum.WNS_STUDENT_LOAN_NOT_EXIST);
        }

        // 删除消息
        List<SmsNewTips> smsNewTipList = smsNewTipsMapper.selectList(new LambdaQueryWrapper<SmsNewTips>().eq(SmsNewTips::getEventId, id));
        if (!smsNewTipList.isEmpty()) {
            List<String> newTipsIdList = smsNewTipList.stream().map(SmsNewTips::getId).collect(Collectors.toList());
            smsNewTipsMapper.deleteBatchIds(newTipsIdList);
            smsNewTipsRecordMapper.delete(new LambdaQueryWrapper<SmsNewTipsRecord>().in(SmsNewTipsRecord::getRecordTipsId, newTipsIdList));
        }
        // 删除申请表
        this.removeById(id);

        // 删除节点
        smsWnsStudentLoanDetailMapper.delete(new LambdaQueryWrapper<SmsWnsStudentLoanDetail>()
                .eq(SmsWnsStudentLoanDetail::getApplyId, id));

        return CommonResult.success();
    }
}
